﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Willows.Model
{
	public partial class Signal 
		: Channel, ISignal
	{
		private List<ISignal> outputs;
		public List<ISignal> Outputs
		{
			get { return outputs; }			
		}

		private ISignal input;
		public ISignal Input
		{
			get { return input; }			
		}

		public void BindOutput(ISignal output)
		{
			if (outputs.Contains(output))
				throw new ArgumentException("Output already bound");

			outputs.Add(output);
		}

		public void UnbindOutput(ISignal output)
		{
			if (!outputs.Contains(output))
			{
				string message = 
					string.Format("Output '{0}' not bound to signal '{1}' (outputs bound: {2})", 
						output.LocalName,
						LocalName,
						outputs.Count
					);

				throw new ArgumentException(message);
			}

			outputs.Remove(output);
		}

		public void BindInput(ISignal input)
		{
			if (this.input != null)
				throw new ArgumentException("Input already bound");

			this.input = input;
		}

		public void UnbindInput(ISignal input)
		{
			if (this.input != input)
				throw new ArgumentException("Input not bound");

			this.input = null;
		}

		public override void Verify(Model model)
		{
		}

		public override List<Module> GetReadingDatapaths()
		{
			throw new NotImplementedException();
		}

		public override Module GetWritingDatapath()
		{
			throw new NotImplementedException();
		}

		public void DatapathMovedUpInHierarchy(Module p1, Module p2)
		{
			// intentionally left empty
		}

		public void DatapathMovedDownInHierarchy(Module p1, Module p2)
		{
			// intentionally left empty
		}

		private static int uniqueNameCnt = 0;
		private static string GetNextUniqueName()
		{
			return string.Format("signal{0}", uniqueNameCnt++);
		}

		public Signal(Module parent, TypeRegistry typeRegistry, Type type)
			: this(parent, typeRegistry, type, GetNextUniqueName())
		{
		}

		/// <summary>
		/// Special constructor. should ONLY be called by the above constructor
		/// </summary>
		private Signal(Module parent, TypeRegistry typeRegistry, Type type, string name)
			: base(parent, typeRegistry, type, name, name)
		{
			this.outputs = new List<ISignal>();
		}

		public Signal(Module parent, TypeRegistry typeRegistry, Type type, string name, string uniqueName)
			: base(parent, typeRegistry, type, name, uniqueName)
		{
			this.outputs = new List<ISignal>();		
		}

		public override void WriteChannelHierarchy(System.CodeDom.Compiler.IndentedTextWriter textWriter)
		{
			textWriter.WriteLine("+====================================================================+");
			textWriter.WriteLine(" Signal LocalName: '{0}' Name: '{1}' Parent '{2}'",
				LocalName,
				Name,
				Parent is HierarchyRoot ? "None" : Parent.LocalName
			);
			textWriter.WriteLine("+====================================================================+");

		}
	}
}
